<?php

namespace App\Task;

use App\Model\Play;
use App\Model\Project;
use App\Model\User;
use App\Utils\Enum\RedbillEnum;
use App\Utils\Enum\UserEnum;

class TestAutoReleaseScheme extends BaseSyncTask
{
    const MIN_TIME = 3600;
    const MAX_TIME = 86400 * 3;

    public function execute(): void
    {
        parent::execute();

        $matchList = Play::whereHas('data', function ($query) {
            $query->whereRaw('odds is not null');
        })->with(['data' => function ($query) {
            $query->select(['match_id', 'odds']);
        }])->whereIn('sport_id', [1, 2])->whereBetween('match_time', [time() + self::MIN_TIME, time() + self::MAX_TIME])->get()->toArray();
        if (empty($matchList)) {
            $this->logger->warning('暂无可发布方案的比赛');
            return;
        }
        $this->logger->warning(sprintf('%d 个比赛可发布方案', count($matchList)));

        $totalUsers = User::query()->where(['role_id' => UserEnum::USER_TYPE_EXPERT, 'is_virtual' => 1])->count();
        $this->logger->warning(sprintf('%d 个专家可发布方案', $totalUsers));
        $num = ceil($totalUsers * 0.1);
        $succ = 0;
        if ($num) {
            $users = User::query()->where('role_id', 3)->orderByRaw('rand()')->limit($num)->get()->toArray();
            foreach ($users as $user) {
                $match = &$matchList[array_rand($matchList)];
                if (Project::query()->where(['userid' => $user['id'], 'match_id' => $match['match_id']])->exists()) {
                    $this->logger->warning(sprintf('专家[userid=%d] 已经发布过该比赛[%s]的方案', $user['id'], $match['match_id']));
                    continue;
                }
                if (!isset($match['odds'])) {
                    $match['odds'] = $this->getOdds($match['data']['odds']);
                    if (empty($match['odds']) || empty($match['odds']['asia']) && empty($match['odds']['bs']) && empty($match['odds']['eu'])) {
                        $this->logger->warning(sprintf('比赛[%s] 赔率空，不可发布 赔率=%s', $match['match_id'], new_json_encode($match['odds'])));
                        break;
                    }
                }
                $ret = $this->releaseScheme($user, $match);
                if ($ret) {
                    $succ++;
                }
            }
        }
        $this->logger->info(sprintf('成功发布%d个方案', $succ));
    }

    /**
     * 发布方案
     * @param $user
     * @param $match
     * @return bool
     */
    private function releaseScheme($user, $match): bool
    {
        //获取玩法
        $playType = $this->getPlayType($match);
        if (!$playType) {
            return false;
        }

        //获取一种推荐
        $suggestResultCode = $this->getSuggestResultCode($playType, $match);

        $oddsAlias = RedbillEnum::getOddsAlias($playType['code']);
        $coins = [28, 38, 48, 58, 68, 78, 88][mt_rand(0, 6)];
        $project = Project::create([
            'project_id' => strtolower(create_randomstr(15)),
            'userid' => $user['id'],
            'sport_id' => $match['sport_id'],
            'play_type_code' => $playType['code'],
            'play_type_name' => $playType['name'],
            'game_id' => $match['game_id'],
            'match_id' => $match['match_id'],
            'match_odds' => new_json_encode($match['odds'][$oddsAlias]),
            'title' => $match['home_team_name'] . ' VS ' . $match['away_team_name'],
            'introduce' => '没有理由，就是强烈推荐!',
            'expert_win_rate' => 0,
            'expert_payback_rate' => 0,
            'status' => RedbillEnum::STATUS_SALE_ING,
            'coins' => $coins,
            'sales' => 0,
            'total_amount' => 0,
            'hit_status' => 0,
            'hits' => 0,
            'suggest_result_code' => new_json_encode($suggestResultCode),
            'real_result_code' => 0,
            'add_time' => time(),
        ]);
        return true;
    }

    /**
     * 获取玩法
     * @param $match
     * @return array
     */
    private function getPlayType($match): array
    {
        $allTypes = RedbillEnum::getPlayList($match['sport_id']);
        $playType = false;
        while (true) {
            if(empty($allTypes)) {
                break;
            }
            $idx = array_rand($allTypes);
            $alias = RedbillEnum::getOddsAlias($allTypes[$idx]['code']);
            if(isset($match['odds'][$alias])) {
                $playType = $allTypes[$idx];
                break;
            } else {
                unset($allTypes[$idx]);
            }
        }
        return $playType;
    }

    private function getSuggestResultCode($playType, $match)
    {
        //获取可选推荐
        $suggestItems = RedbillEnum::getSuggestItemList($playType['code']);

        $suggestResultCode = [];
        if (count($suggestItems) == 2) {
            //胜负 随机推荐一个
            $suggestResultCode = [$suggestItems[mt_rand(0, 1)]['code']];
        } else {
            $luck = mt_rand(1, 3);
            if ($luck == 1) {
                //胜平负 推荐一个
                $suggestResultCode = [$suggestItems[mt_rand(0, 1)]['code']];
            } else {
                $luck = mt_rand(0, 1);
                if ($luck == 1) {
                    //主推 胜，次推 平
                    $suggestResultCode = array_column(array_slice($suggestItems, 0, 2), 'code');
                } else {
                    //主推 平，次推 负
                    $suggestResultCode = array_column(array_slice($suggestItems, 1, 2), 'code');
                }
            }
        }
        return $suggestResultCode;
    }

    /**
     * 获取赔率
     * @param $odds
     * @param $companyId
     * @return array
     */
    private function getOdds($odds, $companyId = 2): array
    {
        if (!is_array($odds)) {
            $odds = new_json_decode($odds);
        }
        $data = [];
        foreach ($odds as $type => $rs) {
            if (!in_array($type, ['asia', 'bs', 'eu']) || empty($rs)) {
                continue;
            }
            if (is_array($rs)) {
                foreach ($rs as $r) {
                    if ($r['company']['id'] == $companyId) {
                        $data[$type] = array_slice($r['f']['odd'], 0, 3);
                    }
                }
            }
        }
        return $data;
    }
}